[BITS 16]

jmp	start

%include "include/defines.inc"
%include "include/io.inc"

; kernel-specific
%include "include/kernel_defines.inc"
%include "include/ctrlbreak_int1Bh.inc"
%include "include/timer_int1Ch.inc"
%include "include/api_int30.inc"
%include "include/api_int31.inc"
%include "include/api_int32.inc"
%include "include/api_int40.inc"
%include "include/aux_proc.inc"
%include "include/console.inc"

start:

; Here we mess with the protected mode.
	cli
	pusha
	lgdt	[gdt_ptr]
	popa
	sti

	cli
	mov	eax,	cr0
	or	eax,	1
	mov	cr0,	eax

	jmp	code:stage3
	

[BITS 32]

stage3:
	mov	ax,	data
	mov	ds,	ax
	mov	ss,	ax
	mov	es,	ax
	mov	esp,	0xFFFFF

;	mov	ax,	0B800h
;	mov	es,	ax
	mov	byte [gs:0],	'A'

;	mov	ah,	1h
;	mov	di,	welcome
;	int	10h

	mov	dl,	0x0A
	xor	ecx,	ecx
	mov	edi,	0xB8000
.rep:	mov	[edi],	byte ' '
	mov	[edi+1],	dl
	add	edi,	2
	inc	ecx
	cmp	ecx,	800h
	jne	.rep

	mov	si,	welcome
	mov	cl,	10
	mov	ch,	10
;;	call	_@printString
;	push	$
;	jmp	_@printString


	mov	edi,	0xB8000	; start of video memory
	mov	[edi+1000],	byte 'A'
	mov	[edi+1001],	byte 0Ah


	mov	ah,	0xA0
	mov	al,	ch
	mul	ah
	add	edi,	eax	; shift to Y
	xor	eax,	eax
	mov	ah,	2
	mov	al,	cl
	mul	ah
	add	edi,	eax	; shift to X
	mov	eax,	esi	; load string address to eax
.rep1:	mov	dl,	[eax]
	cmp	dl,	0Dh	; ignore CR ...
	je	.skip
	cmp	dl,	0Ah	; ... and LF
	je	.skip
	mov	[edi],	dl
	mov	[edi+1],	byte 0x0A
.skip:	inc	eax
	add	edi,	2
	cmp	byte [eax],	0
	jne	.rep1

; set data for new kernel
;	mov	ax,	KERNEL_ENTRY	; set DS to point at new kernel
;	mov	ds,	ax	;	...
;	mov	es,	ax
;	mov	ss,	ax

;	mov	ah,	0xE
;	mov	bl,	0x7
;	mov	al,	'A'

;	mov	byte [0x00010000],	0xC3
;	call	[0x00010000]

	jmp	$

;	jmp	KERNEL_ENTRY

; jump to new kernel that was read from HDD	
;	jmp	KERNEL_ENTRY:0000h

; function to load kernel from HDD
;	readSector:
;		mov     [word lba_dap+4],	si	; where to place
;		mov	[word lba_dap+6],	ds
;		mov	[dword lba_dap+8],	ebx	; address (bits 63..32)
;		mov	[dword lba_dap+12],	edx	; address (bits 31..0)
;		mov	ah,	42h
;		mov	dl,	[disknum]
;		mov	si,	lba_dap
;		int	13h
;		ret
;	ret
; data
;	lba_dap	db	10h	; used by function int32h:10h
;		db	0h
;		dw	1h
;		dw	0h		; sector offset (sector)
;		dw	0h	; sector segment (KERNEL_ENTRY)
;		dq	0000000000000000h	; what sector to read?
; function end

;[BITS 16]

gdt:
	dd	0
	dd	0
code	equ	$-gdt
	dw	0FFFFh
	dw	0
	db	0
	db	9Ah
	db	0CFh
	db	0
data	equ	$-gdt
	dw	0FFFFh
	dw	0
	db	0
	db	92h
	db	0CFh
	db	0

gdt_end:
gdt_ptr:
	dw	gdt_end - gdt - 1
	dd	gdt

idt:
	dw	0h
	dw	code
	db	0
	db	11100000b
	dw	0h


; Jump to kernel start (skip functions)

;; print test char
;	mov	ah,	0xE	; print char
;	mov	al,	'A'
;	mov	bh,	0x0	; page
;	mov	bl,	0x7	; style
;	int	10h

jmp	kernelStart

%include "include/defines.inc"
%include "include/io.inc"

; kernel-specific
%include "include/kernel_defines.inc"
%include "include/ctrlbreak_int1Bh.inc"
%include "include/timer_int1Ch.inc"
%include "include/api_int30.inc"
%include "include/api_int31.inc"
%include "include/api_int32.inc"
%include "include/api_int40.inc"
%include "include/aux_proc.inc"
%include "include/console.inc"

; Kernel entry point
kernelStart:
	mov	[disknum],	dl
	push	es		; save ES
	pushf			; save FLAGS

	cli			; disable interrupts
	push	0
	pop	es		; 0 -> ES

; initializing interrupt 1Bh (CTRL+C handler)
	mov	ax,	int1Bh_handler
	mov	[es:1Bh*4],	ax
	mov	word [es:1Bh*4+2],	KERNEL_ENTRY	; this is our kernel segment start address

; initializing interrupt 1Ch (i8254 timer)
	mov	ax,	int1Ch_handler
	mov	[es:1Ch*4],	ax
	mov	word [es:1Ch*4+2],	KERNEL_ENTRY	; this is our kernel segment start address

; initializing interrupt 30h
	mov	ax,	int30h_handler
	mov	[es:30h*4],	ax
	mov	word [es:30h*4+2],	KERNEL_ENTRY	; this is our kernel segment start address

; initializing interrupt 31h
	mov	ax,	int31h_handler
	mov	[es:31h*4],	ax
	mov	word [es:31h*4+2],	KERNEL_ENTRY	; this is our kernel segment start address

; initializing interrupt 32h
	mov	ax,	int32h_handler
	mov	[es:32h*4],	ax
	mov	word [es:32h*4+2],	KERNEL_ENTRY	; this is our kernel segment start address

; initializing interrupt 40h
	mov	ax,	int40h_handler
	mov	[es:40h*4],	ax
	mov	word [es:40h*4+2],	KERNEL_ENTRY	; this is our kernel segment start address

; revert changes
	popf			; restore FLAGS
	pop	es		; restore ES
	sti			; enable interrupts

; clear screen
;	mov	ah,	0	; function 0h
;	int	30h		; clear screen

; print welcome text
	mov	ah,	1h
	mov	si,	hello
	int	30h

; print kernel entry address
	mov	ah,	1h
	mov	esi,	entry
	int	30h		; print string
	mov	ah,	3
	mov	edx,	cs
	int	30h		; print number
	mov	ah,	1
	mov	esi,	crlf
	int	30h		; print CR/LF

	mov	eax,	0x1000
	mov	es,	eax
	mov	ah,	3
	mov	dx,	es
	int	30h

	mov	ah,	1
	mov	esi,	crlf
	int	30h		; print CR/LF

; get vendor
	mov	ah,	1	; function 1h
	mov	si,	vendor	; string buffer
	int	30h		; print string

	call	PrintVendor

; LBA & DAP test

;	mov	edx,	00000000h	;
;	mov	ebx,	00000101h	; First sector of file system
;	mov	si,	sector
;	mov	ah,	10h
;	int	32h
	mov	edx,	00000000h	;
	mov	ebx,	00000102h	; First sector of file system
;	mov	si,	sector
	mov	si,	node
	mov	ah,	10h
	int	32h

	; print CR-LF
	mov	ah,	1	; function 1h
	mov	si,	crlf	; CR/LF
	int	30h		; print string

; set hardware timer i8254 to 20hz
	mov	dx,	TIMER_0_PORT
	mov	ax,	TIMER_0_M0
	out	dx,	ax

	mov	dx,	TIMER_0_PORT
	mov	ax,	0xE90B
	out	dx,	ax	; MS/LS

	mov	eax,	node
	add	eax,	FLFS_Node.data

	call	eax


;	mov	ah,	1h
;	mov	si,	fsinfo
;	int	30h

;	mov	ah,	77h
;	int	32h


;	mov	ebx,	str1
;	mov	dl,	's'
;;	mov	edx,	str2
;	mov	ah,	1h
;	int	40h

;	xor	ah,	ah	; clear MS of AX (AL contains 0 or 1)

;	mov	dx,	ax
;	mov	ah,	3h
;	int	30h

	mov	ah,	0h
	mov	al,	66d
	mov	edx,	path1
	int	32h

	mov	ah,	1h
	mov	si,	retcode
	int	30h

	xor	ah,	ah
	mov	dx,	ax
	mov	ah,	3h
	int	30h

;	mov	ax,	4F02h
;	mov	bx,	115h	; 800x600 24-bit (8:8:8)
;	int	10h


;	mov	ah,	3
;	mov	dx,	cs
;	int	30h

;	cli
;	mov	eax,	cr0
;	or	al,	1
;	mov	cr0,	eax
;	sti

;	mov	al,	byte [hello]
;	mov	byte [dword 0xFFFFFFFE],	al
;	mov	byte [dword 0xFFFFFFFF],	al

	mov	ax,	0B800h
	mov	es,	ax
	mov	al,	byte [hello]
	mov	ch,	'0'
	mov	cl,	'1'
	mov	byte [es:510], ch
	mov	byte [es:511], 48d
	mov	byte [es:514], cl
	mov	byte [es:515], 48d

	mov	ax,	0B800h
	mov	es,	ax
	mov	al,	byte [hello]
	mov	byte [es:514], al

;	mov	ax,	0
;	mov	es,	ax
;	mov	dword [dword 0x00012340],	0x66FFE000	; jmp eax
;	mov	eax,	done
;	jmp	dword	0x00012340

;	mov	ah,	1
;	mov	si,	node+FLFS_Node.data
;	int	30h			; Print sector to screen (will print #0,"ROOT NODE",#0,#0,#0,...)

;	mov	eax,	cr0
;	or	eax,	1
;	mov	cr0,	eax

done:

; pre-info done

	call	PrintConsolePrefix
	
	mov	bx,	0
	
CL_InputLoop:

	mov	ah,	0x01	; Get new keystroke
	int	31h
	
	cmp	al,	0x0D	; check if Enter key pressed
	je	.cr
	
	cmp	al,	0x08
	je	.bckspc
	
	cmp	al,	0x0A
	je	CL_InputLoop
	
	cmp	al,	0
	je	CL_InputLoop
	
	cmp	al,	0x09
	je	CL_InputLoop
	
	cmp	bx,	MAX_COMMAND_LEN ; check if maximum command lenght reached
	je	CL_InputLoop
	
	mov	[CommandLine+bx],	al	; store current symbol
	inc	bx
	
	push	bx
	mov	ah,	0x0E	; output current symbol to screen
	mov	bl,	0x07
	int	10h
	;mov	dx,ax
	;mov	dh,0
	;mov	ah,	3
	;int	30h		; print number
	pop	bx
	jmp	CL_InputLoop
	
	
	.bckspc:
	cmp	bx,	0
	je	CL_InputLoop
	dec	bx
	push	bx
	mov	ah,	0x0E	; output current symbol to screen
	mov	bl,	0x07
	int	10h
	mov	al,	20h
	int	10h
	mov	al,	08h
	int	10h
	pop	bx
	jmp	CL_InputLoop
	
	
	.cr:	; case if enter key pressed
	push	bx
	mov	ah,	0x0E	; print CR/LF
	mov	bl,	0x07
	int	10h
	mov	al,	0x0A
	mov	ah,	0x0E
	mov	bl,	0x07
	int	10h
	pop	bx
	cmp	bx,	0	; check if command line lenght is non-zero
	je	.@@1
	mov	ax,	CommandLine
	call	ProcessCommand
	mov	bx,	0
.@@1:	call	PrintConsolePrefix
	jmp	CL_InputLoop

	hello	db	" > AOS kernel v0.0 alpha.",13,10," > Created by Anderson & Alexx",13,10," > Greetings!",13,10,0
	entry	db	" > Kernel located at physical address ",0
	vendor	db	" > System running at ",0
	fsinfo	db	" * File system contents:",13,10,0
	console_prefix	db	" < ",0
	unknown_command	db	" > Command or file not found",13,10,0
	CommandLine	times (MAX_COMMAND_LEN) db 0,0
	crlf	db	13,10,0
	disknum	db	0	; disk number

	str1	db	'test',0
	str2	db	'test',0	; for string comparation test

	retcode	db	'Return code:',0

	path1	db	'@/home/anderson/documents/test.odt',0

	node:	istruc	FLFS_Node
;		at	FLFS_Node.data,	db	0
;		at	FLFS_Node.data,	db	0xC3
	iend

	sector	times 8192 db 'X'
	asd	db	0

;	end	db	10,10,10,10,10,10,10,10,10,10

	; Align kernel size to 128k
		times (2016-2-17)*512 - ($ - $$) db 0	; reserve 256-2=254 sectors (31744 bytes), 2 sectors for MBR & VBR
		; !!!!!!!!! 17 = IMAGE.HDD SIZE / 512
;		db 13,10,'Hello, world!',13,10,0
;		times 1000 db 0
